/*
 * Copyright 2010-2012 Susanta Tewari. <freecode4susant@users.sourceforge.net>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package coalescent.is.cef.pui.pob;

import cef.pui.pob.Builder;
import cef.pui.pob.BuilderException;
import coalescent.is.Samplers_K69;
import coalescent.model.K69;
import coalescent.statistic.K69_AC;
import commons.core.Duration;
import commons.core.ValueTypes;
import commons.is.Sampler_Multi;
import commons.util.ValidationUtil;

import javax.xml.bind.PropertyException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Properties;

import static coalescent.cef.pui.pob.Builders_Coa.of_AC_K69_GT_File;
import static coalescent.cef.pui.pob.Builders_Coa.of_Models_K69;

/**
 * Builder for value type {@code Collection<Sampler<?>>}. The available properties are:
 * <ul>
 *     <li>{@code coalescent.is.MultiISamplers.gt_EGT = true | false. If true, the properties specified
 *          in } {@link coalescent.cef.pui.pob.Builders_Coa#of_AC_K69_GT_File(java.util.Properties, String)
 *          GeneTree} {@code and } {@link coalescent.cef.pui.pob.Builders_Coa#of_Model_K69(java.util.Properties, String)
 *          K69} {@code need to be present as well.}
 *     </li>
 *     <li>{@code coalescent.is.MultiISamplers.gt_SD =
 *         true | false. If true, the properties specified in } {@link coalescent.cef.pui.pob.Builders_Coa#of_AC_K69_GT_File(java.util.Properties, String)
 *         GeneTree} {@code and } {@link coalescent.cef.pui.pob.Builders_Coa#of_Model_K69(java.util.Properties, String)
 *         K69} {@code need to be present as well.}
 *     </li>
 *     <li>{@code coalescent.builder.K69List.theta.min = valid double string as specified in } {@link Double#parseDouble(java.lang.String)}</li>
 *     <li>{@code coalescent.builder.K69List.theta.max = valid double string as specified in } {@link Double#parseDouble(java.lang.String)}</li>
 *     <li>{@code coalescent.builder.K69List.theta.increment = valid double string as specified in } {@link Double#parseDouble(java.lang.String)}</li>
 * </ul>
 *
 * @author Susanta Tewari
 * @version version
 * @history Created on Aug 2, 2012.
 * @since since
 */
public class Samplers_Multi_Bldr extends Builder<Collection<Sampler_Multi<?>>> {

    private static final String propKey_ItrType            = "itrType";
    private static final String ItrType_Options_SampleSize = "sampleSize";
    private static final String ItrType_Options_Time       = "time";

    /** value for the chosen iteration type */
    private static final String propKey_ItrValue = "itrTypeVal";
    private final String acPrefix;

    public Samplers_Multi_Bldr(final Properties props, final String prefix, String acPrefix) {

        super(prefix, props);

        this.acPrefix = acPrefix;

        addPropertyKey(Samplers_K69.GT_EGT);
        addPropertyKey(Samplers_K69.GT_SD);
        addPropertyKey(Samplers_K69.GT_HUW);
        addPropertyKey(propKey_ItrType);
        addPropertyKey(propKey_ItrValue);
    }

    @Override
    protected Collection<Sampler_Multi<?>> buildFromProps() throws BuilderException {

        final Collection<Sampler_Multi<?>> samplers = new ArrayList<>(4);
        final List<K69> models                      = of_Models_K69(props, null).build();


        // load the computations
        if (loadProp(Samplers_K69.GT_EGT)) samplers.add(of_GT_EGT(models));
        if (loadProp(Samplers_K69.GT_SD)) samplers.add(of_GT_SD(models));
        if (loadProp(Samplers_K69.GT_HUW)) samplers.add(of_GT_HUW(models));


        // itr type
        String itrType    = getProperty(getFullPropertyKey(propKey_ItrType));
        String itrTypeVal = getProperty(getFullPropertyKey(propKey_ItrValue));

        for (Sampler_Multi<?> sampler : samplers) {

            switch (itrType) {

                case ItrType_Options_SampleSize :
                    final long sampleSize = Long.parseLong(itrTypeVal);

                    sampler.setIteratorBySampleSize(sampleSize);

                    break;

                case ItrType_Options_Time :
                    final int time = new Duration(itrTypeVal).toMillis();

                    sampler.setIteratorByTime(time);

                    break;

                default :
                    throw new IllegalStateException("invalid iteration type");
            }
        }

        return samplers;
    }

    public Builder<ValueTypes.ColorMap> getColorMapBuilder() {
        return Samplers_Bldr.getColorMapBuilder(props, this);
    }

    @Override
    public String getBuilderString() {
        return "NotYetNecessary";
    }

    /**
     * @param prop
     * @return
     * @throws cef.pui.pob.BuilderException
     */
    protected boolean loadProp(final String prop) throws BuilderException {

        final String propertyKey = getFullPropertyKey(prop);
        final String propVal     = getProperty(propertyKey);

        if (propVal == null) return false;

        try {
            ValidationUtil.validateProperty(propertyKey, getProperty(propertyKey));
        } catch (PropertyException ex) {
            throw new BuilderException("Invalid property for Samplers_Multi_Bldr", ex);
        }

        final boolean result;

        try {
            result = Boolean.parseBoolean(getProperty(propertyKey));
        } catch (NumberFormatException ex) {
            throw new BuilderException("", ex);
        }

        return result;
    }

    private Sampler_Multi<?> of_GT_EGT(final List<K69> models) {

        final Builder<K69_AC> bldr = of_AC_K69_GT_File(props, acPrefix);

        return Samplers_K69.of_GT_EGT_Multi(bldr.build(), 500, models);
    }

    private Sampler_Multi<?> of_GT_SD(final List<K69> models) {

        final Builder<K69_AC> bldr = of_AC_K69_GT_File(props, acPrefix);

        return Samplers_K69.of_GT_SD_Multi(bldr.build(), 500, models);
    }

    private Sampler_Multi<?> of_GT_HUW(final List<K69> models) {

        final Builder<K69_AC> bldr = of_AC_K69_GT_File(props, acPrefix);

        return Samplers_K69.of_GT_HUW_Multi(bldr.build(), 500, models);
    }
}
